home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / t3_1 / pmax.lha / pmax / dynload.c next >
C/C++ Source or Header  |  1991-08-14  |  13KB  |  483 lines

  1. /* Changed to support COFF format used by MIPS. Assumes Ultrix 4.1 or more recent. */
  2. /* All changes are ifdef'd mips, so can use for sparc, etc.  R. Osborne  July 9/91 */
  3.  
  4. /*
  5.  *            D Y N L O A D . C 
  6.  *
  7.  * This file contains functions to help dynamically load foreign UNIX files
  8.  * into a running T process.
  9.  *
  10.  * written by Dorab Patel <dorab@neptune.cs.ucla.edu>
  11.  * December 24, 1986
  12.  * Copyright Dorab Patel (C) 1986
  13.  * Permission is given to distribute this software free to anyone
  14.  * using it for a non-commercial purpose. Comments/bug reports/fixes
  15.  * are encouraged.
  16.  *
  17.  * $Revision: 1.1 $
  18.  *
  19.  * $Log:    dynload.c,v $
  20.  * Revision 1.1  86/12/24  18:20:44  dorab
  21.  * Initial Revision
  22.  * 
  23.  */
  24. #ifndef lint
  25. static char RCSid[] = "@(#)$Header: dynload.c,v 1.1 86/12/24 18:20:44 dorab UCLA $ (Exp)";
  26. #endif
  27.  
  28. #include <stdio.h>        /* for obvious reasons */
  29. #ifdef mips
  30. #include <sys/exec.h>    /* on Ultrix RISC, sys/exec.h defines the BSD-like exec structure for a.out format */
  31.  /* Following copied from <a.out.h>: */
  32. #define    A_MAGIC1    0407        /* normal */
  33. #define    A_MAGIC0    0401        /* lpd (UNIX/RT) */
  34. #define    A_MAGIC2    0410        /* read-only text */
  35. #define    A_MAGIC3    0411        /* separated I&D */
  36. #define    A_MAGIC4    0405        /* overlay */
  37. #define    A_MAGIC5    0437        /* system overlay, separated I&D */
  38.  
  39.  /* in invocation of BADMAG macro, argument should not be a function. */
  40.  
  41. #define BADMAG(X) (X.a_magic != A_MAGIC1 &&\
  42.          X.a_magic != A_MAGIC2 &&\
  43.         X.a_magic != A_MAGIC3 &&\
  44.         X.a_magic != A_MAGIC4 &&\
  45.         X.a_magic != A_MAGIC5 &&\
  46.         X.a_magic != A_MAGIC0)
  47. #else
  48. #include <a.out.h>        /* for obvious reasons */
  49. #endif
  50. #include <sys/types.h>        /* for caddr_t */
  51. #include <strings.h>        /* for strlen */
  52.  
  53. /*
  54.  * dont turn this on unless you want copious debugging.
  55.  * it may also have unwanted interactions with sbrk.
  56.  */
  57. #undef DEBUG
  58.  
  59.  
  60. /*
  61.  * alloca is used by default for efficiency. if you need to use
  62.  * malloc, then define USE_MALLOC
  63.  */
  64. #undef USE_MALLOC
  65.  
  66. /* forward declarations */
  67. caddr_t sbrk();
  68. char *sprintf();
  69. #ifdef USE_MALLOC
  70. char *malloc();
  71. #else ~USE_MALLOC
  72. char *alloca();
  73. #endif ~USE_MALLOC
  74.  
  75. /*
  76.  * loadhelp takes an object file (objFile), and loads it
  77.  * into the current process, using relocation information found in the
  78.  * namelist of relocFile. In the process, it will create
  79.  * tmpFile, which has all the current relocation info and which can
  80.  * be used for a subsequent load. In addition, libString
  81.  * is used to search any required libraries.
  82.  * otherString can be used for other ld arguments.
  83.  * Returns 0 if all ok, >0 otherwise.
  84.  * It closes all files it has opened and unlinks the temp file
  85.  * if there has been an error.
  86.  * 
  87.  * TODO:
  88.  * do i need to round up the text/data sizes to word boundaries ?
  89.  */
  90.  
  91. /*
  92.  * the sprintf string for the ld command
  93.  * if this changes, also modify the code for ldCmdSpace
  94.  */
  95. #define LoadCommandTemplate "/bin/ld -N -x -A %s -T %lx %s %s -o %s %s -lc"
  96.  
  97. int
  98. loadhelp(objFile, relocFile, tmpFile, libString, otherString)
  99. char *objFile, *relocFile, *tmpFile, *libString, *otherString;
  100. {
  101. char *loadCommand;        /* pointer to string containing the ld cmd */
  102. int ldCmdSpace;            /* space allocated for ld command */
  103. char buf[BUFSIZ];        /* for buffering tmpFile i/o */
  104. struct exec hdr;
  105. long loadPoint, endOfMem, pageSize, tmp;
  106. FILE *tmpFD = NULL;
  107. long bytesToRead, bytesToExtend;
  108.  
  109. /*
  110.  * calculate the length of the ld command and allocate memory for it
  111.  * this code would need changing if LoadCommandTemplate was changed
  112.  */
  113. ldCmdSpace = strlen(LoadCommandTemplate);
  114. ldCmdSpace += strlen(objFile) + strlen(relocFile) + strlen(tmpFile);
  115. ldCmdSpace += strlen(libString) + strlen(otherString);
  116. ldCmdSpace += 16;    /* 10 for loadPoint + 1 for null + fudge of 5 */
  117.  
  118. #ifdef DEBUG
  119. (void)fprintf(stderr,"loadhelp: ld cmd needs %d bytes\n", ldCmdSpace);
  120. #endif DEBUG
  121.  
  122. #ifdef USE_MALLOC
  123. loadCommand = malloc((unsigned)ldCmdSpace);
  124. #else ~USE_MALLOC
  125. loadCommand = alloca(ldCmdSpace);
  126. #endif ~USE_MALLOC
  127.  
  128. if ((long)loadCommand == 0) {
  129. #ifdef DEBUG
  130.     perror("loadhelp");
  131.     (void)fprintf(stderr,
  132.               "loadhelp: could not allocate %d bytes for ld cmd\n",
  133.               ldCmdSpace);
  134. #endif DEBUG
  135. #ifdef USE_MALLOC
  136.     free(loadCommand);
  137. #endif USE_MALLOC
  138.     return(1);
  139.     }
  140.  
  141. pageSize = (long) getpagesize(); /* works on vaxen, suns, and mips  */
  142. /* there is a strong assumption that pageSize is a power of 2 */
  143.  
  144. #ifdef DEBUG
  145. (void)fprintf(stderr,"loadhelp: page size is %ld (%lx)\n", pageSize, pageSize);
  146. #endif DEBUG
  147.  
  148. endOfMem = (long) sbrk(0); /* get end of current memory */
  149. if (endOfMem < 0) {
  150. #ifdef DEBUG
  151.     perror("loadhelp");
  152.     (void)fprintf(stderr,"loadhelp: sbrk(0) failed\n");
  153. #endif DEBUG
  154. #ifdef USE_MALLOC
  155.     free(loadCommand);
  156. #endif USE_MALLOC
  157.     return(2);
  158.     }
  159.  
  160. #ifdef DEBUG
  161. (void)fprintf(stderr,"loadhelp: end of memory = %ld (%lx)\n",
  162.                 endOfMem, endOfMem);
  163. #endif DEBUG
  164.  
  165. /* round up to the next higher pageSize */
  166. loadPoint = (long) sbrk((int)(pageSize - (endOfMem & (pageSize - 1L))));
  167.  
  168. if (loadPoint < 0L) {
  169. #ifdef DEBUG
  170.     perror("loadhelp");
  171.     (void)fprintf(stderr,"loadhelp: could not bump upto pagesize\n");
  172. #endif DEBUG
  173. #ifdef USE_MALLOC
  174.     free(loadCommand);
  175. #endif USE_MALLOC
  176.     return(3);
  177.     }
  178.  
  179. #ifdef mips
  180. loadPoint = (long) sbrk(0) + pageSize*4;  /* Hack to counter change in break value after fopen */
  181. #else
  182. loadPoint = (long) sbrk(0);
  183. #endif
  184.  
  185. /*
  186.  * there had better be no further calls to sbrk explicitly or implicitly
  187.  * (e.g. via calling printf or something like that) until the loading is
  188.  * over.
  189.  */
  190.  
  191. /* sanity check */
  192. if (loadPoint < 0L || ((loadPoint & (pageSize - 1L)) != 0L)) {
  193. #ifdef DEBUG
  194.     perror("loadhelp");
  195.     (void)fprintf(stderr,"loadhelp: not page aligned\n");
  196. #endif DEBUG
  197. #ifdef USE_MALLOC
  198.     free(loadCommand);
  199. #endif USE_MALLOC
  200.     return(4);
  201.     }
  202.  
  203. #ifdef DEBUG
  204. (void)fprintf(stderr,"loadhelp: load point is %ld (%lx)\n",
  205.                 loadPoint, loadPoint);
  206. #endif DEBUG
  207.  
  208. (void)sprintf(loadCommand, LoadCommandTemplate,
  209.     relocFile, loadPoint, otherString, objFile, tmpFile, libString);
  210.  
  211. /* if the sprintf overflows it'll probably botch BAD, but just in case */
  212. if (strlen(loadCommand) >= ldCmdSpace) {
  213. #ifdef DEBUG
  214.     (void)fprintf(stderr,
  215.               "loadhelp: load command greater than %d byte buffer\n",
  216.               ldCmdSpace);
  217. #endif DEBUG
  218. #ifdef USE_MALLOC
  219.     free(loadCommand);
  220. #endif USE_MALLOC
  221.     return(5);
  222.     }
  223.  
  224. #ifdef DEBUG
  225. (void)fprintf(stderr,"loadhelp: the load command is \"%s\"\n", loadCommand);
  226. (void)fprintf(stderr,"loadhelp: Before ld break= %lx\n", sbrk(0));
  227. #endif DEBUG
  228.  
  229. /* run the ld comand to do relocation */
  230. if (system(loadCommand) != 0 ) {
  231. #ifdef DEBUG
  232.     perror("loadhelp");
  233.     (void)fprintf(stderr,"loadhelp: error in executing the ld command\n");
  234. #endif DEBUG
  235. #ifdef USE_MALLOC
  236.     free(loadCommand);
  237. #endif USE_MALLOC
  238.     return(6);
  239.     }
  240.  
  241. #ifdef DEBUG
  242. (void)fprintf(stderr,"loadhelp: After ld break= %lx\n", sbrk(0));
  243. #endif DEBUG
  244.  
  245. /* open the relocated file */
  246. tmpFD = fopen(tmpFile, "r");
  247. if (tmpFD == NULL ) {
  248. #ifdef DEBUG
  249.     perror("loadhelp");
  250.     (void)fprintf(stderr, "loadhelp: could not open %s for read\n",
  251.                   tmpFile);
  252. #endif DEBUG
  253. #ifdef USE_MALLOC
  254.     free(loadCommand);
  255. #endif USE_MALLOC
  256.     return(7);
  257.     }
  258.  
  259. #ifdef DEBUG
  260. (void)fprintf(stderr,"loadhelp: After fopen break= %lx\n", sbrk(0));
  261. #endif DEBUG
  262.  
  263. /*
  264.  * use buf to buffer tmpFile so that no mallocs can occur
  265.  * since buf is automatic, tmpFD must be closed upon exit from this routine
  266.  */
  267. (void)setbuf(tmpFD,buf);
  268.  
  269. /* read its header */
  270. if (fread((char *)&hdr, sizeof(struct exec), 1, tmpFD) != 1) {
  271. #ifdef DEBUG
  272.     perror("loadhelp");
  273.     (void)fprintf(stderr,"loadhelp: error reading header of %s\n", tmpFile);
  274.     if (fclose(tmpFD) == EOF) perror("loadhelp"); /* close tmp file */
  275.     if (unlink(tmpFile)) perror("loadhelp"); /* remove it */
  276. #else ~DEBUG
  277.     (void)fclose(tmpFD);    /* close tmp file */
  278.     (void)unlink(tmpFile);    /* remove it */
  279. #endif ~DEBUG
  280. #ifdef USE_MALLOC
  281.     free(loadCommand);
  282. #endif USE_MALLOC
  283.     return(8);
  284.     }
  285.  
  286. #ifdef DEBUG
  287. (void)fprintf(stderr,"loadhelp: After fread break= %lx\n", sbrk(0));
  288. #endif DEBUG
  289.  
  290. #ifdef mips
  291. if (BADMAG(hdr)) {
  292. #else
  293. if (N_BADMAG(hdr)) {
  294. #endif
  295. #ifdef DEBUG
  296.     (void)fprintf(stderr,"loadhelp: bad magic number %o in %s\n",
  297.                   hdr.a_magic, tmpFile);
  298.     if (fclose(tmpFD) == EOF) perror("loadhelp"); /* close tmp file */
  299.     if (unlink(tmpFile)) perror("loadhelp"); /* remove it */
  300. #else ~DEBUG
  301.     (void)fclose(tmpFD);    /* close tmp file */
  302.     (void)unlink(tmpFile);    /* remove it */
  303. #endif ~DEBUG
  304. #ifdef USE_MALLOC
  305.     free(loadCommand);
  306. #endif USE_MALLOC
  307.     return(9);
  308.     }
  309.  
  310. #ifdef DEBUG
  311. (void)fprintf(stderr,
  312.   "loadhelp: magic = %o, text = %ld(%lx), data = %ld(%lx), bss = %ld(%lx)\n",
  313.                hdr.a_magic, hdr.a_text,
  314.                hdr.a_text, hdr.a_data,
  315.                hdr.a_data, hdr.a_bss, hdr.a_bss);
  316. #endif DEBUG
  317.  
  318. bytesToRead = hdr.a_text + hdr.a_data;
  319. bytesToExtend = bytesToRead + hdr.a_bss;
  320.  
  321. #ifdef DEBUG
  322. (void)fprintf(stderr,
  323.           "loadhelp: going to read %ld bytes and extend by %ld bytes\n",
  324.                bytesToRead, bytesToExtend);
  325. #endif DEBUG
  326.  
  327. #ifdef mips
  328. tmp = (long) sbrk(0);       /* check break */
  329.  
  330. if (tmp <= loadPoint) /* No problem: we're still within preallocated change in break value */
  331.     brk(loadPoint);   /* so shift break */
  332. else {
  333.     fprintf(stderr, "Load failed: break value changed by more than preallocated!\n");
  334. #ifdef DEBUG
  335.     if (fclose(tmpFD) == EOF) perror("loadhelp"); /* close tmp file */
  336.     if (unlink(tmpFile)) perror("loadhelp"); /* remove it */
  337. #else ~DEBUG
  338.     (void)fclose(tmpFD);    /* close tmp file */
  339.     (void)unlink(tmpFile);    /* remove it */
  340. #endif ~DEBUG
  341. #ifdef USE_MALLOC
  342.     free(loadCommand);
  343. #endif USE_MALLOC
  344.     return(11);
  345.     }
  346. #endif
  347.  
  348.  
  349. /* get required memory */
  350. tmp = (long) sbrk((int)bytesToExtend);
  351. if (tmp < 0L) {
  352. #ifdef DEBUG
  353.     perror("loadhelp");
  354.     (void)fprintf(stderr,"loadhelp: not enough memory\n");
  355.     if (fclose(tmpFD) == EOF) perror("loadhelp"); /* close tmp file */
  356.     if (unlink(tmpFile)) perror("loadhelp"); /* remove it */
  357. #else ~DEBUG
  358.     (void)fclose(tmpFD);    /* close tmp file */
  359.     (void)unlink(tmpFile);    /* remove it */
  360. #endif ~DEBUG
  361. #ifdef USE_MALLOC
  362.     free(loadCommand);
  363. #endif USE_MALLOC
  364.     return(10);
  365.     }
  366.  
  367. /* some last sanity checks */
  368. if (tmp != loadPoint) {
  369. #ifdef DEBUG
  370.     (void)fprintf(stderr,
  371.               "loadhelp: load point is %ld (%lx) but sbrk returns %ld (%lx)\n",
  372.                   loadPoint, loadPoint, tmp, tmp);
  373.     if (fclose(tmpFD) == EOF) perror("loadhelp"); /* close tmp file */
  374.     if (unlink(tmpFile)) perror("loadhelp"); /* remove it */
  375. #else ~DEBUG
  376.     (void)fclose(tmpFD);    /* close tmp file */
  377.     (void)unlink(tmpFile);    /* remove it */
  378. #endif ~DEBUG
  379. #ifdef USE_MALLOC
  380.     free(loadCommand);
  381. #endif USE_MALLOC
  382.     return(11);
  383.     }
  384.  
  385.  
  386. if (tmp & (pageSize - 1L)) {
  387. #ifdef DEBUG
  388.     (void)fprintf(stderr,
  389.               "loadhelp: allocated memory at %ld -not page aligned\n");
  390.     if (fclose(tmpFD) == EOF) perror("loadhelp"); /* close tmp file */
  391.     if (unlink(tmpFile)) perror("loadhelp"); /* remove it */
  392. #else ~DEBUG
  393.     (void)fclose(tmpFD);    /* close tmp file */
  394.     (void)unlink(tmpFile);    /* remove it */
  395. #endif ~DEBUG
  396. #ifdef USE_MALLOC
  397.     free(loadCommand);
  398. #endif USE_MALLOC
  399.     return(12);
  400.     }
  401.  
  402. /* go to beginning of text */
  403. #ifdef mips
  404. if (fseek(tmpFD,(long)N_TXTOFF(hdr.ex_f,hdr.ex_o),0) < 0) {
  405. #else
  406. if (fseek(tmpFD,(long)N_TXTOFF(hdr),0) < 0) {
  407. #endif
  408. #ifdef DEBUG
  409.     perror("loadhelp");
  410.     (void)fprintf(stderr,"loadhelp: fseek failed on %s\n", tmpFile);
  411.     if (fclose(tmpFD) == EOF) perror("loadhelp"); /* close tmp file */
  412.     if (unlink(tmpFile)) perror("loadhelp"); /* remove it */
  413. #else ~DEBUG
  414.     (void)fclose(tmpFD);    /* close tmp file */
  415.     (void)unlink(tmpFile);    /* remove it */
  416. #endif ~DEBUG
  417. #ifdef USE_MALLOC
  418.     free(loadCommand);
  419. #endif USE_MALLOC
  420.     return(13);
  421.     }
  422.  
  423.  
  424. /* read the text and data segments in */
  425. if (fread((char *)loadPoint, 1, (int)bytesToRead, tmpFD) != (int)bytesToRead) {
  426. #ifdef DEBUG
  427.     perror("loadhelp");
  428.     (void)fprintf(stderr, "loadhelp: could not read data from %s\n",
  429.                   tmpFile);
  430.     if (fclose(tmpFD) == EOF) perror("loadhelp"); /* close tmp file */
  431.     if (unlink(tmpFile)) perror("loadhelp"); /* remove it */
  432. #else ~DEBUG
  433.     (void)fclose(tmpFD);    /* close tmp file */
  434.     (void)unlink(tmpFile);    /* remove it */
  435. #endif ~DEBUG
  436. #ifdef USE_MALLOC
  437.     free(loadCommand);
  438. #endif USE_MALLOC
  439.     return(14);
  440.     }
  441.  
  442.  
  443. #ifdef DEBUG
  444. if (fclose(tmpFD) == EOF) perror("loadhelp");
  445. #else ~DEBUG
  446. (void)fclose(tmpFD);
  447. #endif ~DEBUG
  448.  
  449. #ifdef USE_MALLOC
  450. free(loadCommand);
  451. #endif USE_MALLOC
  452.  
  453. return(0);
  454. }
  455.  
  456.  
  457. /*
  458.  * return the address of the function functionName in the namelist 
  459.  * of the file fileName.
  460.  * the calling procedure had better make sure that fileName exists.
  461.  */
  462.  
  463. /* Defined in pmaxassist.c
  464. /*unsigned long
  465. /*nlistone(fileName,functionName)
  466. /*char *fileName, *functionName;
  467. /*{
  468. /*struct nlist nl[2];
  469. /*int rc;
  470. /*
  471. /*nl[1].n_un.n_name = '\0'; /* terminate the name list */
  472. /*nl[0].n_un.n_name = functionName; /* put the function name in */
  473. /*rc = nlist(fileName,nl); /* call nlist */
  474. /*if (rc < 0 || (nl[0].n_type == (unsigned char) 0 /* check for errors */
  475. /*       && nl[0].n_value == (unsigned long) 0))
  476. /*    return ((unsigned long) 0);
  477. /*if (nl[0].n_type & N_TEXT) /* if it is in the text segment i.e. is a function */
  478. /*    return(nl[0].n_value); /* return the address */
  479. /*else
  480. /*    return ((unsigned long) 0); /* not a function */
  481. /*}
  482. */
  483.